package Sdo.sftp;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.filechooser.FileSystemView;

import org.apache.log4j.Logger;

import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import Sdo.sftp.JschTools;
import Sdo.terminalfx.helper.ThreadHelper;
import Sdo.pojo.History;
import Sdo.pojo.PFile;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.TextInputDialog;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.ImageView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;

public class FileViewfx extends Tab {

	private static Logger logger = Logger.getLogger(FileViewfx.class);

	ObservableList<PFile> data = FXCollections.observableArrayList();
	TableView<PFile> table;
	String ScpPath = "/";// 初始化成“/”
	TextField serverpathText = new TextField("/");// 初始化
	final DirectoryChooser dirChooser = new DirectoryChooser();
	String toDir;
	File desktopDir = FileSystemView.getFileSystemView().getHomeDirectory();
	String desktopPath = desktopDir.getAbsolutePath();
	Button localpathBtn = new Button("本地目录:"+desktopPath);
	JschTools exp;
	ProgressBar pbar;
	VBox vb = new VBox();

	Label systemInfo = new Label();

	public void setInfoText(String info, Long tm) {

		ThreadHelper.start(() -> {
			ThreadHelper.runActionLater(() -> {
				Label txtInfo = new Label();
				txtInfo.setAlignment(Pos.CENTER);
				txtInfo.setTextFill(Color.web("#ff0000", 0.8));

				vb.getChildren().add(txtInfo);
				txtInfo.setManaged(true);
				txtInfo.setVisible(true);
				txtInfo.setText(info);
				if (tm > 0) {
					Timer t = new Timer();
					t.schedule(new TimerTask() {

						@Override
						public void run() {
							// TODO Auto-generated method stub
							txtInfo.setManaged(false);
							txtInfo.setVisible(false);
							t.cancel();
						}
					}, tm, 1);
				}
			});

		});

	}

	@SuppressWarnings("unchecked")
	public FileViewfx(History history) throws IOException {
		ThreadHelper.start(() -> {
			ThreadHelper.runActionLater(() -> {
				data.clear();
			});

		});
		table = new TableView<PFile>();

		TableColumn<PFile, ImageView> ImageCol = new TableColumn<PFile, ImageView>("类型");

		TableColumn<PFile, String> NameCol = new TableColumn<PFile, String>("文件名");

		TableColumn<PFile, String> SizeCol = new TableColumn<PFile, String>("大小");

//		TableColumn<PFile, String> AtimeCol = new TableColumn<PFile, String>("创建时间");
//
//		TableColumn<PFile, String> MtimeCol = new TableColumn<PFile, String>("修改时间");

		TableColumn<PFile, String> PCol = new TableColumn<PFile, String>("权限");

		TableColumn<PFile, String> tCol = new TableColumn<PFile, String>("是否文件夹");// 类型隐藏不显示

		ImageCol.setCellValueFactory(new PropertyValueFactory<PFile, ImageView>("image"));

		ImageCol.setStyle("-fx-alignment: CENTER;");
		NameCol.setCellValueFactory(new PropertyValueFactory<PFile, String>("filename"));
		NameCol.setMinWidth(400);
		SizeCol.setCellValueFactory(new PropertyValueFactory<PFile, String>("size"));
//
//		AtimeCol.setCellValueFactory(new PropertyValueFactory<PFile, String>("atime"));
//
//		MtimeCol.setCellValueFactory(new PropertyValueFactory<PFile, String>("mtime"));

		PCol.setCellValueFactory(new PropertyValueFactory<PFile, String>("permissions"));

		tCol.setCellValueFactory(new PropertyValueFactory<PFile, String>("dir"));
		tCol.setVisible(false);
		// table.getColumns().addAll(ImageCol, NameCol, SizeCol, AtimeCol, MtimeCol,
		// PCol, tCol);
		table.getColumns().addAll(ImageCol, NameCol, SizeCol, PCol, tCol);
		
		ThreadHelper.start(() -> {
			ThreadHelper.runActionLater(() -> {
				Ready(history);
			});

		});

		ThreadHelper.start(() -> {
			ThreadHelper.runActionLater(() -> {

				localpathBtn.setAlignment(Pos.BASELINE_LEFT);
				localpathBtn.prefWidthProperty().bind(vb.widthProperty());
				pbar = new ProgressBar();
				pbar.prefWidthProperty().bind(vb.widthProperty());

				pbar.setVisible(false);
				pbar.setManaged(false);
				BorderPane pane = new BorderPane();
				vb.prefWidthProperty().bind(pane.widthProperty());

				systemInfo.setAlignment(Pos.CENTER);
				systemInfo.setTextFill(Color.web("#ff0000", 0.8));
				systemInfo.setVisible(false);
				systemInfo.setManaged(false);

				vb.getChildren().addAll(serverpathText, localpathBtn, pbar, systemInfo);

				pane.setTop(vb);
				pane.setCenter(table);
				this.setContent(pane);

			});

		});

		this.setOnClosed(new EventHandler<Event>() {
			@Override
			public void handle(Event event) {
				// TODO Auto-generated method stub
				ThreadHelper.start(() -> {
					ThreadHelper.runActionLater(() -> {
						exp.close();

					});

				});

			}
		});
		serverpathText.setOnKeyPressed(new EventHandler<KeyEvent>() {
			@Override
			public void handle(KeyEvent ke) {

				if (ke.getCode().equals(KeyCode.ENTER)) {

					ThreadHelper.start(() -> {
						ThreadHelper.runActionLater(() -> {
							data.clear();
						});

					});

					ScpPath = serverpathText.getText();

					ThreadHelper.start(() -> {
						ThreadHelper.runActionLater(() -> {
							try {

								data = exp.getHostPath(ScpPath);

							} catch (SftpException e) {
								// TODO Auto-generated catch block

								ThreadHelper.runActionLater(() -> {

									setInfoText("获取路径失败" + e.getMessage(), (long) 5000);

								});

								e.printStackTrace();
							} catch (JSchException e) {
								// TODO Auto-generated catch block
								ThreadHelper.runActionLater(() -> {
									setInfoText("登陆失败！" + e.getMessage(), (long) 0);

								});
								e.printStackTrace();
							} catch (IOException e) {
								logger.debug(e.getMessage());
							}

							table.setItems(data);

						});
					});

				}

			}
		});

		localpathBtn.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent event) {
				// TODO Auto-generated method stub

				ThreadHelper.start(() -> {

					ThreadHelper.runActionLater(() -> {
						File file = dirChooser.showDialog(new Stage());
						if (file != null) {
							
							desktopPath=file.getPath();
							//localpathBtn.setText("本地目录:"+file.getPath());
						} else {
							//localpathBtn.setText("本地目录:"+desktopPath);
						}
						localpathBtn.setText("本地目录:"+desktopPath);
					});
				});

			}
		});

	}

	public void Ready(History history) {
		ThreadHelper.start(() -> {
			ThreadHelper.runActionLater(() -> {

				try {
					exp = new JschTools(history);
				} catch (JSchException e) {
					// TODO Auto-generated catch block
					setInfoText("服务器链接失败" + e.getMessage(), (long) 0);

				}

				Refresh(exp, ScpPath);
				tableBindAction(history);

				table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
			});
		});

		final ContextMenu contextMenu = new ContextMenu();

		final MenuItem closeOthers = new MenuItem("Close Others");
		final MenuItem closeAll = new MenuItem("Close All");

		closeAll.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent event) {
				// TODO Auto-generated method stub
				ThreadHelper.start(() -> {
					ThreadHelper.runActionLater(() -> {

						getTabPane().getTabs().clear();

					});
				});
			}
		});
		closeOthers.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent event) {
				// TODO Auto-generated method stub
				final ObservableList<Tab> tabs = FXCollections.observableArrayList(getTabPane().getTabs());
				ArrayList<Tab> markedTabs = new ArrayList<>();
				for (final Tab tab : tabs) {

					if (tab != getTabPane().getSelectionModel().getSelectedItem())
						markedTabs.add(tab);
				}

				getTabPane().getTabs().removeAll(markedTabs);
			}
		});

		contextMenu.getItems().addAll(closeOthers, closeAll);
		this.setContextMenu(contextMenu);

	}

	private void Refresh(JschTools exp, String SPath) {
		// TODO Auto-generated method stub
		ThreadHelper.runActionLater(() -> {

			serverpathText.setText(SPath);
			data.clear();
			try {
				data = exp.getHostPath(SPath);
			} catch (SftpException e) {
				ThreadHelper.runActionLater(() -> {
					setInfoText("刷新列表失败" + e.getMessage(), (long) 5000);

				});
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (JSchException e) {
				// TODO Auto-generated catch block
				ThreadHelper.runActionLater(() -> {

					setInfoText("登陆失败，请检查联系信息" + e.getMessage(), (long) 0);

				});
				e.printStackTrace();
			} catch (IOException e) {
				logger.debug(e.getMessage());
			}
			table.setItems(data);

		});

	}

	public void tableBindAction(History history) {

		table.setOnDragOver(new EventHandler<DragEvent>() {

			@Override
			public void handle(DragEvent event) {
				event.acceptTransferModes(TransferMode.ANY);
				event.consume(); //
				// System.out.println("Drop setOnDragOver!");
			}
		});

		// Enable a label to be dropped on this label
		table.setOnDragDropped(new EventHandler<DragEvent>() {
			@Override
			public void handle(DragEvent event) {

				Dragboard dragboard = event.getDragboard();
				List<File> files = dragboard.getFiles();

				if (files.size() > 0) {
					for (File file : files) {

						ThreadHelper.start(() -> {
							try {
								exp.putfile(file, serverpathText.getText(), pbar, systemInfo);
							} catch (SftpException e) {
								// TODO Auto-generated catch block

								ThreadHelper.runActionLater(() -> {

									setInfoText("目录没有写入权限" + e.getMessage(), (long) 5000);

								});

								// e.printStackTrace();
							} catch (FileNotFoundException e) {
								// TODO Auto-generated catch block

								ThreadHelper.runActionLater(() -> {
									setInfoText("文件不存在" + e.getMessage(), (long) 5000);

								});
								e.printStackTrace();
							} catch (JSchException e) {
								// TODO Auto-generated catch block

								ThreadHelper.runActionLater(() -> {

									setInfoText("服务器链接异常" + e.getMessage(), (long) 5000);

								});
								e.printStackTrace();
							}

						});

					}
					Refresh(exp, ScpPath);
					// 等待处理测试
				}

			}
		});
//	    
//			
//		table.setOnDragExited(new EventHandler<DragEvent>() {
//			public void handle(DragEvent event) {
//
//	    		ThreadHelper.runActionLater(() -> {
//	    			
//
//		        	
//					// System.out.println("drag left!");
//					Dragboard dragboard = event.getDragboard();
//					List<java.io.File> files = dragboard.getFiles();
//					if (files.size() > 0) {
//						java.io.File f = files.get(0);
//						ThreadHelper.start(() -> {
//						try {
//							exp.uploadFile(f, serverpathText.getText(), null);
//							Refresh(exp, ScpPath);
//							
//							
//						} catch (IOException e) {
//							// TODO Auto-generated catch block
//							e.printStackTrace();
//						}
//						 });
//					}
//
//				
//	    			
//	    			
//	    		});
//	        	
//	        
//			}
//		});

//		 
//		    table.setOnDragDone(new EventHandler<DragEvent>() {
//		        public void handle(DragEvent event) {}
//		    });
//		  
		table.setRowFactory(tv -> {
			TableRow<PFile> row = new TableRow<>();

			row.setOnMouseClicked(new EventHandler<MouseEvent>() {
				@Override
				public void handle(MouseEvent event) {
					if (event.getClickCount() == 2 && (!row.isEmpty())) {
						ThreadHelper.start(() -> {
							PFile rowData = row.getItem();
							openFile(history, rowData);

						});

					}

				}
			});

			// 拖拽节点
			row.setOnDragDetected(new EventHandler<MouseEvent>() {
				@Override
				public void handle(MouseEvent event) {

					if (!row.isEmpty()) {
						PFile rowData = row.getItem();
						Dragboard dragboard = row.startDragAndDrop(TransferMode.ANY);
						ClipboardContent content = new ClipboardContent();
						content.putString(rowData.getFilename());
						dragboard.setContent(content);
					}
				}
			});

//			row.setOnDragEntered(new EventHandler<DragEvent>() {
//	 
//				
//				@Override
//				public void handle(DragEvent event) {
//					System.out.println(">>>>"+toDir);
//				}
//			});
//			
//			
//			row.setOnDragExited(new EventHandler<DragEvent>() {
//
//				@Override
//				public void handle(DragEvent event) {
//					if (!row.isEmpty()) {
//						PFile rowData = row.getItem();
//						// System.out.println(rowData.getFilename());
//						toDir = rowData.getFilename();
//					}
//				}
//			});

			row.setOnDragOver(new EventHandler<DragEvent>() {

				@Override
				public void handle(DragEvent event) {
					if (event.getGestureSource() != row && event.getDragboard().hasString() && !row.isEmpty()) {
						event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
						PFile rowData = row.getItem();
						toDir = rowData.getFilename();

					}
				}
			});

////			
			row.setOnDragDropped(new EventHandler<DragEvent>() {

				@Override
				public void handle(DragEvent event) {

//					Dragboard dragboard = event.getDragboard();
//					String spath = dragboard.getString();
					ObservableList<PFile> pf = table.getSelectionModel().getSelectedItems();
//					System.out.println(">>>>"+spath.indexOf(0));
//					System.out.println(">>>>"+spath.indexOf(1));

					if ("".equals(toDir) || toDir == null || pf.isEmpty() || toDir.isEmpty()) {
					} else {

						String newpath = ScpPath + "/" + toDir;
						if ("..".equals(toDir)) {

							newpath = ScpPath.substring(0, ScpPath.lastIndexOf("/"));
						} else if (".".equals(toDir) || "".equals(newpath)) {
							newpath = "/";// 直接复制到根目录
						}
						String mpath = newpath;

						ThreadHelper.start(() -> {

							for (PFile pFile : pf) {
								String oldpath = ScpPath + "/" + pFile.getFilename();
								try {
									exp.mv(oldpath, mpath, systemInfo);
								} catch (SftpException e) {
									// TODO Auto-generated catch block

									ThreadHelper.runActionLater(() -> {

										setInfoText("移动操作失败" + e.getMessage(), (long) 5000);

									});
									e.printStackTrace();
								} catch (JSchException e) {
									// TODO Auto-generated catch block

									ThreadHelper.runActionLater(() -> {

										setInfoText("移动操作失败" + e.getMessage(), (long) 5000);

									});
									e.printStackTrace();
								}

							}

							Refresh(exp, ScpPath);

						});

						toDir = "";

					}

				}
			});
//			
			// 非空白处菜单
			ContextMenu cm = new ContextMenu();
			MenuItem open = new MenuItem("打开");
			MenuItem download = new MenuItem("下载");
			MenuItem rename = new MenuItem("修改名称");
			MenuItem delete = new MenuItem("删除");
			MenuItem refresh = new MenuItem("刷新");
			cm.getItems().addAll(open, download, rename, delete, refresh);

			// 空白处的菜单
			ContextMenu dm = new ContextMenu();

			MenuItem createdir = new MenuItem("新建文件夹");

			dm.getItems().addAll(createdir, refresh);

			row.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
				@Override
				public void handle(MouseEvent t) {

					if (t.getButton() == MouseButton.SECONDARY) {

						if (!row.isEmpty()) {
							cm.show(table, t.getScreenX(), t.getScreenY());
						} else {
							dm.show(table, t.getScreenX(), t.getScreenY());
						}
						PFile rowData = row.getItem();
						open.setOnAction((ActionEvent e) -> {

							ThreadHelper.start(() -> {
								openFile(history, rowData);

							});

						});
						download.setOnAction((ActionEvent e) -> {

							ThreadHelper.start(() -> {
								ObservableList<PFile> pf = table.getSelectionModel().getSelectedItems();
								if (!pf.isEmpty()) {
									for (PFile pFile : pf) {
										try {
											exp.getfile(pFile.isDir(), serverpathText.getText(), pFile.getFilename(),
													desktopPath, pbar, systemInfo);
										} catch (SftpException e1) {

											ThreadHelper.runActionLater(() -> {
												setInfoText("下载失败！" + e1.getMessage(), (long) 5000);
//														

											});
											// TODO Auto-generated catch block
											e1.printStackTrace();
										} catch (JSchException e1) {
											// TODO Auto-generated catch block

											ThreadHelper.runActionLater(() -> {
												setInfoText("下载失败！" + e1.getMessage(), (long) 5000);
//														
											});
											e1.printStackTrace();
										}
									}

								}

							});

						});
						rename.setOnAction(new EventHandler<ActionEvent>() {

							@Override
							public void handle(ActionEvent event) {
								PFile rowData = row.getItem();

								TextInputDialog dialog = new TextInputDialog(rowData.getFilename());
								dialog.setTitle("修改文件名");
								dialog.setHeaderText(null);
								dialog.setContentText("文件夹名:");
								Optional<String> result = dialog.showAndWait();

								if (result.isPresent()) {
									ThreadHelper.start(() -> {
										try {
											exp.Rename(serverpathText.getText() + "/" + rowData.getFilename(),
													serverpathText.getText() + "/" + result.get());
											table.getItems().remove(row.getIndex());
											PFile file = exp.getFileInfo(serverpathText.getText() + "/" + result.get(),
													result.get());
											table.getItems().add(file);
										} catch (SftpException e) {

											ThreadHelper.runActionLater(() -> {

												setInfoText("名称修改操作失败" + e.getMessage(), (long) 5000);
											});
											// TODO Auto-generated catch block
											e.printStackTrace();
										} catch (JSchException e) {
											// TODO Auto-generated catch block
											e.printStackTrace();
										} catch (IOException e) {
											logger.debug(e.getMessage());
										}

									});
								}

							}
						});
						createdir.setOnAction((ActionEvent e) -> {

							TextInputDialog dialog = new TextInputDialog("新建文件夹");
							dialog.setTitle("新建文件夹");
							dialog.setHeaderText(null);
							dialog.setContentText("文件夹名:");

							// Traditional way to get the response value.
							Optional<String> result = dialog.showAndWait();

							if (result.isPresent()) {
								ThreadHelper.start(() -> {

									try {
										exp.mkDir(serverpathText.getText() + "/" + result.get());
										PFile file = exp.getFileInfo(serverpathText.getText() + "/" + result.get(),
												result.get());
										table.getItems().add(file);

									} catch (SftpException e1) {

										ThreadHelper.runActionLater(() -> {

											setInfoText("创建文件夹失败" + e1.getMessage(), (long) 5000);

										});
										// TODO Auto-generated catch block
										e1.printStackTrace();

									} catch (JSchException e1) {
										// TODO Auto-generated catch block
										e1.printStackTrace();
									} catch (IOException e1) {
										logger.debug(e1.getMessage());
									}

								});

								// Refresh(exp, ScpPath);
							}

						});

						delete.setOnAction((ActionEvent e) -> {

							Alert alert = new Alert(AlertType.CONFIRMATION);
							alert.setTitle("操作确认");
							alert.setHeaderText(null);
							alert.setContentText("确认删除吗，一旦删除无法恢复?");

							Optional<ButtonType> result = alert.showAndWait();
							ObservableList<PFile> pf = table.getSelectionModel().getSelectedItems();
							if (result.get() == ButtonType.OK) {
								// ... user chose OK
								ThreadHelper.start(() -> {
									try {
										if (!pf.isEmpty()) {
											exp.rmfile(serverpathText.getText(), pf);
											table.getItems().removeAll(pf);
//											for (PFile pFile : pf) {
//												
//											}
										}
									} catch (JSchException e1) {
										// TODO Auto-generated catch block

										ThreadHelper.runActionLater(() -> {

											setInfoText("删除操作失败" + e1.getMessage(), (long) 5000);

										});
										e1.printStackTrace();
									}
								});
								// Refresh(exp, ScpPath);

								// table.refresh();
							} else {
								// ... user chose CANCEL or closed the dialog
//								Platform.runLater(new Runnable() {
//									@Override
//									public void run() {
//											Notifications noca = Notifications.create().title("操作取消").text("取消删除").graphic(null)
//													.hideAfter(Duration.seconds(3)).position(Pos.TOP_RIGHT)
//													.onAction(new EventHandler<ActionEvent>() {
//														@Override
//														public void handle(ActionEvent event) {
//															// TODO Auto-generated method stub
//															System.out.println("test");
//														}
//													});
//											noca.showConfirm();
//									}
//								});
							}

						});

						refresh.setOnAction(e -> {
							Refresh(exp, ScpPath);
						});

					}

					if (t.getButton() == MouseButton.MIDDLE || t.getButton() == MouseButton.PRIMARY) {

						if (cm.isShowing()) {
							cm.hide();

						}
						if (dm.isShowing()) {
							dm.hide();
						}

					}

				}
			});

			return row;
		});

	}

	public void openFile(History history, PFile rowData) {
		if (rowData.getFilename().equals(".")) {
			ScpPath = "/";
		} else if (rowData.getFilename().equals("..")) {
			if (ScpPath.equals("/")) {
			} else {
				ScpPath = ScpPath.substring(0, ScpPath.lastIndexOf("/"));
			}

		} else {
			if (ScpPath.equals("/")) {
				ScpPath = "/" + rowData.getFilename();
			} else {
				ScpPath = ScpPath + "/" + rowData.getFilename();
			}

		}
		if ("".equals(ScpPath)) {
			ScpPath = "/";
		}

		if (rowData.isDir()) {

			// 文件直接打开
			Refresh(exp, ScpPath);

		} else {

			ThreadHelper.runActionLater(() -> {
				setInfoText("当前文件不是文件夹", (long) 5000);

			});
		}

	}

}
